﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using ProgNetComponentsDx.Browsers;
using ProgNetComponentsDx.Browsers.Design.Editors;
using System.Drawing.Design;
using ProgNetComponents.Classes;
using ProgNetComponentsDx.Forms;
using ProgNetComponentsDx.Mode;
using DevExpress.XtraEditors;

namespace BuildHelper.Work.Template
{
    public partial class TemplateControl : UserControl
    {
        public ModeProvider ControllerModeProvider
        {
            get { return modeProvider1.ControllerModeProvider; }
            set { modeProvider1.ControllerModeProvider = value; }
        }

        public TemplateControl()
        {
            InitializeComponent();
            AllowAdd = false;
        }
        private Browser browser = null;
        private NamedObject parameter = new NamedObject("@NAZWA", null);
        private string _TemplateName;
        private int _ButtonHeight = 26;
        private int _ButtonWidth = 80;

        private bool _Vertical;
        public bool Vertical
        {
            get
            {
                return _Vertical;
            }
            set
            {
                if (_Vertical != value)
                {
                    _Vertical = value;
                    tableLayoutPanel1.SuspendLayout();
                    tableLayoutPanel1.Controls.Clear();
                    if (value)
                    {
                        for (int row = 0; row < tableLayoutPanel1.RowStyles.Count;row++ )
                        {
                            if (row == 3)
                            {
                                tableLayoutPanel1.RowStyles[row].SizeType = SizeType.Percent;
                                tableLayoutPanel1.RowStyles[row].Height = 100;
                            }
                            else
                                tableLayoutPanel1.RowStyles[row].SizeType = SizeType.AutoSize;
                            
                        }

                        tableLayoutPanel1.ColumnStyles[0].SizeType = SizeType.Percent;
                        tableLayoutPanel1.ColumnStyles[0].Width = 100;

                        for (int col = 1; col < tableLayoutPanel1.ColumnStyles.Count; col++)
                            tableLayoutPanel1.ColumnStyles[col].SizeType = SizeType.AutoSize;

                        lueSzablon.Anchor = AnchorStyles.Top;
                        btnReadTemplate.Anchor = AnchorStyles.Top;
                        btnAdd.Anchor = AnchorStyles.Top;
                        btnSaveTemplate.Anchor = AnchorStyles.Top;
                        btnSaveAs.Anchor = AnchorStyles.Top;

                        int i = 0;
                        tableLayoutPanel1.Controls.Add(lueSzablon, 0, i++);
                        tableLayoutPanel1.Controls.Add(btnReadTemplate, 0, i++);
                        tableLayoutPanel1.Controls.Add(btnAdd, 0, i++);
                        i++;
                        tableLayoutPanel1.Controls.Add(btnSaveTemplate, 0, i++);
                        tableLayoutPanel1.Controls.Add(btnSaveAs, 0, i++);
                    }
                    else
                    {
                        for (int col = 0; col < tableLayoutPanel1.ColumnStyles.Count; col++)
                        {
                            if (col == 3)
                            {
                                tableLayoutPanel1.ColumnStyles[col].SizeType = SizeType.Percent;
                                tableLayoutPanel1.ColumnStyles[col].Width = 100;
                            }
                            else
                                tableLayoutPanel1.ColumnStyles[col].SizeType = SizeType.AutoSize;
                        }
                        tableLayoutPanel1.RowStyles[0].SizeType = SizeType.Percent;
                        tableLayoutPanel1.RowStyles[0].Height = 100;
                        
                        for (int row = 1; row < tableLayoutPanel1.RowStyles.Count; row++)
                            tableLayoutPanel1.RowStyles[row].SizeType = SizeType.AutoSize;

                        lueSzablon.Anchor = AnchorStyles.None;
                        btnReadTemplate.Anchor = AnchorStyles.None;
                        btnAdd.Anchor = AnchorStyles.None;
                        btnSaveTemplate.Anchor = AnchorStyles.None;
                        btnSaveAs.Anchor = AnchorStyles.None;
                        
                        int i = 0;
                        tableLayoutPanel1.Controls.Add(lueSzablon, i++, 0);
                        tableLayoutPanel1.Controls.Add(btnReadTemplate, i++, 0);
                        tableLayoutPanel1.Controls.Add(btnAdd, i++, 0);
                        i++;
                        tableLayoutPanel1.Controls.Add(btnSaveTemplate, i++, 0);
                        tableLayoutPanel1.Controls.Add(btnSaveAs, i++, 0);
                    }
                    tableLayoutPanel1.ResumeLayout(true);
                }
            }
        }
        private object _BrowserId;
        [Editor(typeof(BrowserNameEditor), typeof(UITypeEditor))]
        public object BrowserId
        {
            get { return _BrowserId; }
            set
            {
                _BrowserId = value;
                browserProvider1.BeginInit();
                browserProvider1.GetSettings(lueSzablon).BrowserId = value;
                browserProvider1.GetSettings(lueSzablon).AddBrowserDialogButton = true;
                browserProvider1.EndInit();
                browser = null;
                if (value.IsNotNull() && !this.IsDesignMode())
                {
                    try
                    {
                        browser = BrowserCache.GetBrowser(value);
                    }
                    catch { }
                }
            }
        }

        public string[] Tables
        {
            get;
            set;
        }
        public bool AllowRead
        {
            get
            {
                return btnReadTemplate.Visible;
            }
            set
            {
                tableLayoutPanel1.SuspendLayout();
                btnReadTemplate.Visible = value;
                btnReadTemplate.Width = ButtonWidth;
                btnReadTemplate.Height = ButtonHeight;
                tableLayoutPanel1.ResumeLayout(true);
                //tableLayoutPanel1.ColumnStyles[0].SizeType = (value ? SizeType.Percent : SizeType.AutoSize);
            }
        }
        public bool AllowAdd
        {
            get { return btnAdd.Visible; }
            set
            {
                tableLayoutPanel1.SuspendLayout();
                btnAdd.Visible = value;
                btnAdd.Width = ButtonWidth;
                btnAdd.Height = ButtonHeight;
                tableLayoutPanel1.ResumeLayout(true);
                //tableLayoutPanel1.ColumnStyles[1].SizeType = (value ? SizeType.Percent : SizeType.AutoSize);
            }
        }

        public bool AllowSave
        {
            get
            {
                return btnSaveTemplate.Visible;
            }
            set
            {
                tableLayoutPanel1.SuspendLayout();
                btnSaveTemplate.Visible = value;
                btnSaveTemplate.Width = ButtonWidth;
                btnSaveTemplate.Height = ButtonHeight;
                tableLayoutPanel1.ResumeLayout(true);
                //tableLayoutPanel1.ColumnStyles[3].SizeType = (value ? SizeType.Percent : SizeType.AutoSize);
            }
        }
        public bool AllowSaveAs
        {
            get
            {
                return btnSaveAs.Visible;
            }
            set
            {
                tableLayoutPanel1.SuspendLayout();
                btnSaveAs.Visible = value;
                btnSaveAs.Width = ButtonWidth;
                btnSaveAs.Height = ButtonHeight;
                tableLayoutPanel1.ResumeLayout(true);
                //tableLayoutPanel1.ColumnStyles[4].SizeType = (value ? SizeType.Percent : SizeType.AutoSize);
            }
        }
        public bool ShowTemplateLookup
        {
            get { return lueSzablon.Visible; }
            set
            {
                tableLayoutPanel1.SuspendLayout();
                lueSzablon.Visible = value;
                tableLayoutPanel1.ResumeLayout(true);
            }
        }
/*
        [Category("Buttons")]
        //public SimpleButton BtnAdd
        {
            get { return this.btnAdd; }
        }
        [Category("Buttons")]
        //public SimpleButton BtnReadTemplate
        {
            get { return this.btnReadTemplate; }
        }
        [Category("Buttons")]
        //public SimpleButton BtnSaveAs
        {
            get { return this.btnSaveAs; }
        }
        [Category("Buttons")]
        //public SimpleButton BtnSaveTemplate
        {
            get { return this.btnSaveTemplate; }
        }
       */
        public bool ClearOnRead { get; set; }
        
        public int ButtonWidth
        {
            get { return _ButtonWidth; }
            set
            {
                _ButtonWidth = value;
                tableLayoutPanel1.SuspendLayout();
                foreach (Control c in tableLayoutPanel1.Controls)
                {
                    if (c is SimpleButton)
                        c.Width = value;
                }
                tableLayoutPanel1.ResumeLayout(true);
            }
        }
       
        public int ButtonHeight
        {
            get { return _ButtonHeight; }
            set
            {
                _ButtonHeight = value;
                tableLayoutPanel1.SuspendLayout();
                foreach (Control c in tableLayoutPanel1.Controls)
                {
                    if (c is SimpleButton)
                        c.Height = value;
                }
                tableLayoutPanel1.ResumeLayout(true);
            }
        }
        public DataSet SourceDataSet
        {
            get;
            set;
        }
        public bool ShowTemplateName
        {
            get;
            set;
        }
        public event EventHandler<MergingDataSetEventArgs> AddingTemplate;
        public event EventHandler<MergingDataSetEventArgs> ReadingTemplate;
        public event EventHandler<MergingDataSetEventArgs> SavingTemplate;
        public event EventHandler TemplateRead;

        protected bool OnAddingTemplate(DataSet ds)
        {
            bool result = false;
            if (AddingTemplate != null)
            {
                MergingDataSetEventArgs e = new MergingDataSetEventArgs(ds);
                AddingTemplate(this, e);
                result = e.Handeled;
            }
            return result;
        }
        protected bool OnReadingTemplate(DataSet ds)
        {
            bool result = false;
            if (ReadingTemplate != null)
            {
                MergingDataSetEventArgs e = new MergingDataSetEventArgs(ds);
                ReadingTemplate(this, e);
                result = e.Handeled;
            }
            return result;
        }
        protected bool OnSavingTemplate(DataSet ds)
        {
            bool result = false;
            if (SavingTemplate != null)
            {
                MergingDataSetEventArgs e = new MergingDataSetEventArgs(ds);
                SavingTemplate(this, e);
                result = e.Handeled;
            }
            return result;
        }
        private TableUniqueColumnsCollection _AddUniqueColumns = new TableUniqueColumnsCollection();

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public TableUniqueColumnsCollection AddUniqueColumns
        {
            get { return _AddUniqueColumns; }
        }
        private bool lockTemplateReading = false;
        private bool isValid()
        {
            if (browser == null || Tables == null || Tables.Length == 0 ||
                SourceDataSet == null)
                return false;
            return true;
        }
        public string TemplateName
        {
            get { return _TemplateName; }
            set
            {
                if (_TemplateName != value)
                {
                    _TemplateName = value;
                    UpdateName();
                }
            }
        }

        public void PerformReadTemplate(string nazwa = null)
        {
            if (isValid())
            {
                DataSet ds = SourceDataSet.Clone();
                if (ReadDs(ds, nazwa))
                {
                    if (!OnReadingTemplate(ds))
                    {
                        SourceDataSet.MergeDataSet(ds, ClearOnRead, Tables);
                        if (TemplateRead != null)
                            TemplateRead(this, EventArgs.Empty);
                    }
                }
            }
        }

        private void btnReadTemplate_Click(object sender, EventArgs e)
        {
            string nazwa = null;
            if (lueSzablon.Visible)
                nazwa = lueSzablon.EditValue.AsString();
            PerformReadTemplate(nazwa);
        }

        private bool ReadDs(DataSet ds, string nazwa = null)
        {
            if (nazwa.IsNullOrEmpty())
            {
                ObjectDialogResult dlg = BrowserCache.ShowBrowserDialog(BrowserId);
                if (dlg.DialogResult == DialogResult.OK)
                {
                    nazwa = dlg.Value.AsString();
                    lockTemplateReading = true;
                    lueSzablon.EditValue = nazwa;
                    lockTemplateReading = false;
                }
            }

            bool res = false;

            if (nazwa.IsNotNullOrEmpty())
            {
                try
                {
                    parameter.Value = nazwa;
                    byte[] bytes = sqlCeDataManager1.ExecuteScalar("SELECT STP_TMP_XML FROM STP_TEMPLATES WHERE " + browser.Filter + " AND STP_TMP_NAZWA = @NAZWA", parameter) as byte[];
                    string xml = bytes.ByteArrayToString();
                    ds.ReadXmlString(xml);
                    res = true;
                    TemplateName = nazwa;
                }
                catch (Exception ex)
                {
                    ex.Log();
                }
            }
            return res;
        }

        private void btnSaveTemplate_Click(object sender, EventArgs e)
        {
            if (isValid())
            {
                DataSet ds = SourceDataSet.Clone();
                ds.MergeDataSet(SourceDataSet, false, Tables);
                Save(ds, true);
            }
        }

        private void btnSaveAs_Click(object sender, EventArgs e)
        {
            if (isValid())
            {
                DataSet ds = SourceDataSet.Clone();
                ds.MergeDataSet(SourceDataSet, false, Tables);
                ObjectDialogResult dlg = browser.ShowDialog();

                if (dlg.DialogResult == DialogResult.OK)
                {
                    string nazwa = dlg.Value.AsString();
                    bool result = SaveDs(ds, nazwa, false);
                    if (result)
                        Form.ActiveForm.ShowDxInfoDialog("Szablon zapisany.");
                    else
                        Form.ActiveForm.ShowDxInfoDialog("Szablon nie zapisany.");
                }
            }
        }
        private bool Save(DataSet ds, bool askForOverride)
        {
            bool result = false;
            BrowserCache.RefreshCacheForBrowser(BrowserId);
            InputForm frm = new InputForm();
            frm.InputMaskType = DevExpress.XtraEditors.Mask.MaskType.RegEx;
            frm.InputMask = ".{0,50}";

            frm.ValidateOnChange = true;

            frm.Tag = askForOverride;
            frm.ValidateValue += new ObjectValidationEventHandler(frm_ValidateText);
            string nazwa = frm.ShowInputDialog("Nazwa szablonu:", Application.ProductName).AsString().Trim();
            bool isNew = !BrowserCache.IsValid(BrowserId, false, nazwa);
            if (nazwa.IsNotNull())
                result = SaveDs(ds, nazwa, isNew);
            if (result)
                frm.ShowDxInfoDialog("Szablon zapisany.");
            else
                frm.ShowDxInfoDialog("Szablon nie zapisany.");

            return result;
        }

        private bool SaveDs(DataSet ds, string str, bool isNew)
        {
            bool res = true;
            try
            {
                if (!OnSavingTemplate(ds))
                {
                    string query = "";
                    string grupa = browser.Filter.GetFirstMatch("STP_TMP_GRUPA\\s*=\\s*'(.*)'");
                    NamedObject p1 = new NamedObject("@GRUPA", grupa);
                    NamedObject p2 = new NamedObject("@NAZWA", str);
                    string xml = ds.WriteXmlString();
                    NamedObject p3 = new NamedObject("@XML", xml.AsByteArray());
                    int i = 0;
                    if (isNew)
                    {
                        query = "INSERT INTO STP_TEMPLATES(STP_TMP_GRUPA, STP_TMP_NAZWA, STP_TMP_XML) VALUES(@GRUPA, @NAZWA,@XML)";
                        i = sqlCeDataManager1.ExecuteNonQuery(query, p1, p2, p3);
                    }
                    else
                    {
                        query = "UPDATE STP_TEMPLATES SET STP_TMP_XML = @XML WHERE STP_TMP_GRUPA = @GRUPA AND STP_TMP_NAZWA = @NAZWA";
                        i = sqlCeDataManager1.ExecuteNonQuery(query, p3, p1, p2);
                    }
                    res = i == 1;
                }
            }
            catch (Exception ex)
            {
                ex.Log();
                res = false;
            }
            if (res)
            {
                BrowserCache.RefreshCacheForBrowser(BrowserId);
                TemplateName = str;
            }
            return res;
        }
        private  void frm_ValidateText(object sender, ObjectValidateEventArgs e)
        {
            bool askForOverride = (sender as Form).Tag.AsBool();

            if (e.Value.IsNull())
                e.ValidationErrorMsg = "Nazwa nie może być pusta.";

            else if (BrowserCache.IsValid(BrowserId, false, e.Value.AsString().Trim()))
            {
                if (askForOverride)
                    if (e.ErrorOnly || (sender as Form).ShowDxYNQuestionDialog("Szablon z tą nazwą istnieje. Chcesz go nadpisać?") == DialogResult.No)
                        e.ValidationErrorMsg = "Nazwa jest juz zajęta.";
            }
        }
        private void btnAdd_Click(object sender, EventArgs e)
        {
            if (isValid())
            {
                DataSet ds = SourceDataSet.Clone();
                if (ReadDs(ds))
                {
                    if (AddUniqueColumns.Count > 0)
                    {
                        TableUniqueColumns tabCols;
                        DataRow[] rows;
                        string query;
                        string val;
                        foreach (string tab in Tables)
                        {
                            tabCols = AddUniqueColumns[tab];

                            if (tabCols != null && tabCols.Columns != null && tabCols.Columns.Length > 0)
                            {
                                rows = ds.Tables[tab].Select();
                                foreach (DataRow r in rows)
                                {
                                    query = "";
                                    foreach (string s in tabCols.Columns)
                                    {
                                        query = query.AppendAnd();
                                        val = r[s].AsString();
                                        if (val.IsNull())
                                            query += s + " IS NULL";
                                        else
                                            query += s + " = " + val.EscapeSql();
                                    }
                                    if (SourceDataSet.Tables[tab].RowExists(query))
                                    {
                                        r.Delete();
                                    }
                                }
                                ds.Tables[tab].AcceptChanges();
                            }
                        }
                    }
                    if (!OnAddingTemplate(ds))
                    {
                        SourceDataSet.MergeDataSet(ds, false, Tables);
                        if (TemplateRead != null)
                            TemplateRead(this, EventArgs.Empty);
                    }
                }
            }
        }
       
        public void UpdateName()
        {
            if (ShowTemplateName)
            {
                this.groupTemplate.Text = "Szablon";
                if (TemplateName.IsNotNull())
                    this.groupTemplate.Text += " [" + TemplateName + "]";
            }
        }

        private void lueSzablon_EditValueChanged(object sender, EventArgs e)
        {
            if (!lockTemplateReading)
                PerformReadTemplate(lueSzablon.EditValue.AsString());
        }
    }

    public class MergingDataSetEventArgs : EventArgs
    {
        private DataSet _TemplateDataSet;
        public DataSet TemplateDataSet
        {
            get { return _TemplateDataSet; }
        }
        public bool Handeled
        {
            get;
            set;
        }
        public MergingDataSetEventArgs(DataSet templateDataSet)
        {
            this._TemplateDataSet = templateDataSet;
        }
    }
    public class TableUniqueColumnsCollection : CollectionBase
    {
        public void Add(TableUniqueColumns value)
        {
            this.List.Add(value);
        }
        public void Remove(TableUniqueColumns value)
        {
            this.List.Remove(value);
        }
        public bool Contains(string table)
        {
            return this[table] != null;
        }
        public TableUniqueColumns this[string table]
        {
            get
            {
                foreach (object t in this.List)
                    if (t is TableUniqueColumns)
                    {
                        if ((t as TableUniqueColumns).Table == table)
                            return t as TableUniqueColumns;
                    }
                return null;
            }
        }
    }

    public class TableUniqueColumns
    {
        public string Table { get; set; }
        public string[] Columns { get; set; }
    }
}
